﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DetectApp.Display;

public class RingCircleControl : ROIControl
{
    private readonly Canvas _canvas;
    private readonly EllipseGeometry _circle1;
    private readonly EllipseGeometry _circle2;
    private readonly List<Shape> _docEllipse = new();
    private readonly Path _ring;
    private Point _circleCenter;
    private double _circleRad;
    private int _docDiameter = 0;
    private double _initRadius = 50;
    private bool _isMove;
    private bool _isRotate;
    private bool _isSCale1;
    private bool _isSCale2;
    private bool _isSCale3;
    private bool _isSCale4;
    private Point _startPoint;
    private double _startTopLeft;
    private double _startTopUp;
    public RingCircleControl(Canvas canvas, Color color)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        Point center = new Point(_canvas.ActualWidth / 2, _canvas.ActualHeight / 2);
        _circle1 = new(center, K * _initRadius, K * _initRadius);
        _circle2 = new(center, K * _initRadius - 10, K * _initRadius - 10);
        CombinedGeometry combinedGeometry = new CombinedGeometry() { GeometryCombineMode = GeometryCombineMode.Exclude };
        combinedGeometry.Geometry1 = _circle1;
        combinedGeometry.Geometry2 = _circle2;
        _ring = new Path
        {
            Data = combinedGeometry,
            Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
            Stroke = new SolidColorBrush(color),
            StrokeThickness = 0.5,
        };
        _ring.MouseEnter += (sender, e) =>
        {
            UpdateEllipse(_ring, canvas);
        };
        _ring.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
        canvas.Children.Add(_ring);
        Canvas.SetLeft(_ring, 0);
        Canvas.SetTop(_ring, 0);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    public RingCircleControl(Canvas canvas, ROIParam rOIParam)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;

        _circle1 = new(rOIParam.aring_center1, rOIParam.aring_radius1, rOIParam.aring_radius1);
        _circle2 = new(rOIParam.aring_center2, rOIParam.aring_radius2, rOIParam.aring_radius2);
        CombinedGeometry combinedGeometry = new CombinedGeometry() { GeometryCombineMode = GeometryCombineMode.Exclude };
        combinedGeometry.Geometry1 = _circle1;
        combinedGeometry.Geometry2 = _circle2;
        _ring = new Path
        {
            Data = combinedGeometry,
            Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
            Stroke = new SolidColorBrush(Colors.Blue),
            StrokeThickness = 0.5,
        };
        _ring.MouseEnter += (sender, e) =>
        {
            UpdateEllipse(_ring, canvas);
        };
        _ring.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
        canvas.Children.Add(_ring);
        Canvas.SetLeft(_ring, rOIParam.Left);
        Canvas.SetTop(_ring, rOIParam.Top);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    public double K { get => _canvas.ActualWidth / 500.0; }
    public override ROIParam GetParam()
    {
        ROIParam roi = new() { ROIType = ROIType.完整圆环 };
        roi.aring_center1 = _circle1.Center;
        roi.aring_center2 = _circle2.Center;
        roi.aring_radius1 = _circle1.RadiusX;
        roi.aring_radius2 = _circle2.RadiusX;
        roi.Left = Canvas.GetLeft(_ring);
        roi.Top = Canvas.GetTop(_ring);
        return roi;
    }

    public override HRegion? GetRegion()
    {
        Point centerPoint = _ring.TranslatePoint(_circle1.Center, _canvas);
        HRegion regionC1 = new HRegion(centerPoint.Y, centerPoint.X, _circle1.RadiusX);
        HRegion regionC2 = new HRegion(centerPoint.Y, centerPoint.X, _circle2.RadiusX);
        return regionC1.Difference(regionC2);
    }

    public override ROIInfo GetROI()
    {
        ROIInfo roi = new() { ROIType = ROIType.完整圆环 };
        roi.aring_center1 = _ring.TranslatePoint(_circle1.Center, _canvas);
        roi.aring_center2 = _ring.TranslatePoint(_circle2.Center, _canvas);
        roi.aring_radius1 = _circle1.RadiusX;
        roi.aring_radius2 = _circle2.RadiusX;
        return roi;
    }

    public override void Remove()
    {
        _canvas.Children.Remove(_ring);
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.LeftButton == MouseButtonState.Released)
        {
            _isMove = false; _isSCale1 = false; _isSCale2 = false; _isSCale3 = false; _isSCale4 = false; _isRotate = false;
        }
        if (!_isSCale1 & !_isSCale2 & !_isSCale3 & !_isSCale4 & !_isMove & !_isRotate)
        {
            bool isClear = true;
            if (_ring.IsMouseOver == true) { isClear = false; }
            foreach (var rect in _docEllipse)
            {
                if (rect.IsMouseOver)
                {
                    isClear = false;
                    break;
                }
            }
            if (isClear)
            {
                _docEllipse.ForEach(e => { _canvas.Children.Remove(e); });
                _docEllipse.Clear();
            };
        }
        if (_isMove)
        {
            Point curPoint = Mouse.GetPosition(_canvas);
            var rPoint = curPoint - _startPoint;
            Canvas.SetLeft(_ring, _startTopLeft + rPoint.X);
            Canvas.SetTop(_ring, _startTopUp + rPoint.Y);
            UpdateEllipse(_ring, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale1)
        {
            Point point = Mouse.GetPosition(_canvas);
            if (_circle1.RadiusX - 1 <= _circle2.RadiusX) return;
            _circle1.RadiusY = (-point.X + _startPoint.X) + _circleRad;
            _circle1.RadiusX = (-point.X + _startPoint.X) + _circleRad;

            UpdateEllipse(_ring, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale2)
        {
            Point point = Mouse.GetPosition(_canvas);
            if (_circle1.RadiusX - 1 <= _circle2.RadiusX) return;
            _circle2.RadiusY = (-point.X + _startPoint.X) + _circleRad;
            _circle2.RadiusX = (-point.X + _startPoint.X) + _circleRad;
            UpdateEllipse(_ring, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
    }

    private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _isMove = true;
        _startPoint = Mouse.GetPosition(_canvas);
        _startTopUp = Canvas.GetTop(_ring);
        _startTopLeft = Canvas.GetLeft(_ring);
    }

    private void UpdateEllipse(Path ring, Canvas canvas)
    {
        //ROIChange?.Invoke(this, EventArgs.Empty);
        _docDiameter = (int)(5 * K);
        Brush fillBrush = new SolidColorBrush(Colors.Blue);
        double opacityK = 1;
        _docEllipse.ForEach(e => { canvas.Children.Remove(e); });
        _docEllipse.Clear();
        Point center = new Point(_circle1.Center.X - _circle1.RadiusX, _circle1.Center.Y);
        Point point = ring.TranslatePoint(center, canvas);
        Ellipse circle1 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle1, point.X - _docDiameter / 2);
        Canvas.SetTop(circle1, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle1);
        _docEllipse.Add(circle1);
        circle1.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale1 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = _circle1.RadiusX;
            _circleCenter.X = Canvas.GetLeft(ring);
            _circleCenter.Y = Canvas.GetTop(ring);
        };
        circle1.MouseLeftButtonUp += (s, e) => { _isSCale1 = false; };

        center = new Point(_circle2.Center.X - _circle2.RadiusX, _circle2.Center.Y);
        point = ring.TranslatePoint(center, canvas);
        Ellipse circle2 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle2, point.X - _docDiameter / 2);
        Canvas.SetTop(circle2, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle2);
        _docEllipse.Add(circle2);
        circle2.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale2 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = _circle2.RadiusY;
            _circleCenter.X = Canvas.GetLeft(ring);
            _circleCenter.Y = Canvas.GetTop(ring);
        };
        circle2.MouseLeftButtonUp += (s, e) => { _isSCale2 = false; };
    }
}